package com.gm.wj.service;

import com.gm.wj.config.RedisConfig;
import com.gm.wj.dao.PtCaptainDAO;
import com.gm.wj.dao.PtMemberDAO;
import com.gm.wj.entity.PtCaptain;
import com.gm.wj.entity.PtMember;
import com.gm.wj.entity.SysCourse;
import com.gm.wj.entity.SysOrder;
import com.gm.wj.redis.RedisService;
import com.gm.wj.util.JsonUtils;
import com.gm.wj.util.MyPage;
import com.gm.wj.util.MyTime;
import com.gm.wj.util.UUidUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 拼团
 */
@Slf4j
@Service
public class PtService {

    @Autowired
    PtCaptainDAO ptCaptainDAO;
    @Autowired
    PtMemberDAO ptMemberDAO;
    @Autowired
    SysCourseService sysCourseService;
    @Autowired
    SysOrderFlowService sysOrderFlowService;
    @Autowired
    RedisService redisService;

    /**
     * 发起拼团，redis缓存订单失效时间、插入拼团数据、插入订单数据
     * @param ptCaptain
     */
    @Transactional
    public Map<String,String> add(String courseId) {
        Map<String, String> map = new HashMap<String, String>();
        PtCaptain ptCaptain = new PtCaptain();
        try {

            // 获取操作用户名
            String username = (String) SecurityUtils.getSubject().getPrincipal();
            ptCaptain.setUsername(username);
            // 雪花id
            ptCaptain.setFatherId(UUidUtils.UID());
            // 3人团
            ptCaptain.setPtNum(3);
            // 课程id --> 拼团商品id
            ptCaptain.setProductId(courseId);
            // 创建时间
            ptCaptain.setCreateTime(MyTime.getStringDate());
            // 结束时间增加15分钟
            ptCaptain.setEndTime(MyTime.dateToStrLong(MyTime.getBeforeTimeForMin(15)));
            // 0:未付款 1:拼团中，2:拼团成功, 3：拼团失败
            ptCaptain.setPtStatus(0);
            // 获取课程信息
            SysCourse sysCourse = sysCourseService.findByCourseId(courseId);
            ptCaptain.setPtTuition(sysCourse.getPtTuition()); // 拼团价格

            //生成订单
            Map<String,String> sysOrderMap  = sysOrderFlowService.addOrder(sysCourse.getId(),username,1);
            if (sysOrderMap.get("code").equals("200")){
                // 设置拼团订单缓存
//                String key = "ptList:" + ptCaptain.getFatherId();
//                redisService.set(key, JsonUtils.objectToJson(ptCaptain),RedisConfig.REDIS_KEY_TIME);  // 单位s
                ptCaptain.setOrderId(sysOrderMap.get("orderId"));
                log.info("开团成功：" + ptCaptain.toString());
                ptCaptainDAO.save(ptCaptain);

                map.put("code", "200");
                map.put("message", "开团成功");
                return map;
            } else {
                map.put("code", "400");
                map.put("message", sysOrderMap.get("message"));
                return map;
            }
        } catch (Exception e) {
            log.info("【拼团】--进入手动事务回滚--" + e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            map.put("code", "400");
            map.put("message", "--进入手动事务回滚--" +e.getMessage());
            return map;
        }

    }

    /**
     * 参团 --> 团员
     * @param fatherId
     * @return
     */
    @Transactional
    public int addMember(String fatherId) {
        // 获取操作用户名
        String username = (String) SecurityUtils.getSubject().getPrincipal();
        try {
            // 判断是否已满3人
            List<PtMember> ptMembers = ptMemberDAO.findByFatherId(fatherId);
            if (ptMembers.size() > 1) {
                return 2;// 拼团已满人
            }

            PtCaptain ptCaptain = ptCaptainDAO.findByFatherId(fatherId);
            PtMember ptMember = new PtMember();
            ptMember.setUsername(username);
            // 父id
            ptMember.setFatherId(fatherId);
            // 子id
            ptMember.setChildrenId(UUidUtils.UID());
            // 发起人
            ptMember.setCaptainId(ptCaptain.getUsername());
            // 商品id
            ptMember.setProductId(ptCaptain.getProductId());
            // 拼团价格
            ptMember.setPtTuition(ptCaptain.getPtTuition());
            // 创建时间
            ptMember.setCreateTime(MyTime.getStringDate());
            // 团单状态  0:未付款 1:加团成功
            ptMember.setPtStatus(0);

            // 设置拼团订单缓存
//            String key = "ptList:" + ptMember.getChildrenId();
//            redisService.set(key, JsonUtils.objectToJson(ptMember),60);  // 单位s

            SysCourse sysCourse = sysCourseService.findByCourseId(ptMember.getProductId());

            Map<String,String> sysOrderMap  = sysOrderFlowService.addOrder(sysCourse.getId(),username,2);
            if (sysOrderMap.get("code").equals("200")){
//                ptCaptain.setOrderId(sysOrderMap.get("orderId"));
                ptMember.setOrderId(sysOrderMap.get("orderId"));
                log.info("参团成功：" + ptMember.toString());
                ptMemberDAO.save(ptMember);
            } else if (sysOrderMap.get("code").equals("401")){
                log.info("【参团】 该课程你已经报名了，不允许重复报名");
                return 3;
            } else {
                log.info("【参团】 库存不足");
                return 2;
            }

            List<PtMember> sysptMembers = ptMemberDAO.findByFatherId(fatherId);
            if (sysptMembers.size() == 2) {
                log.info("【参团】参团后判断人数--->{}，正在设置2:拼团成功",sysptMembers.size());
                // 0:未付款 1:拼团中，2:拼团成功, 3：拼团失败
                ptCaptainDAO.updateStatus(ptCaptain.getId(),2);
            }

            return 1;  // 参团成功
        } catch (Exception e) {
            log.info(e.getMessage());
            log.info("【参团】--进入手动事务回滚--" );
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return 0;
        }
    }

    /**
     * 订单支付完成之后。就开始计算拼团订单倒计时。如果拼团在规定时间没完成就过期
     * @param orderId
     */
    public void setRedisStartByPt(String FatherId){
        // 设置订单缓存
        String key = "ptCaptainList:" + FatherId;
        redisService.set(key, JsonUtils.objectToJson(FatherId), RedisConfig.REDIS_KEY_TIME);  // 单位s 设置15分钟后过期
    }


    /**
     * 根据商品id 查询状态为1:拼团中，2:拼团成功的商品
     * @param ptCaptain
     */
    public List<PtCaptain> findByCourse(String productId) {
            List<PtCaptain> ptCaptains = ptCaptainDAO.findByPtStatusIng(productId);
            return ptCaptains;
    }

    /**
     * 根据父id查询子商品
     * @param ptMembers
     */
    public List<PtMember> findChildrenByFatherId(String fatherId) {
        List<PtMember> ptMembers = ptMemberDAO.findByFatherId(fatherId);
        return ptMembers;
    }

    public MyPage list(int page, int size) {
        MyPage<PtCaptain> ptCaptains;
        Sort sort = Sort.by(Sort.Direction.DESC, "id");
        Page<PtCaptain> ptCaptainsInDb = ptCaptainDAO.findAll(PageRequest.of(page, size, sort));
        ptCaptains = new MyPage<>(ptCaptainsInDb);
        return ptCaptains;
    }

    /**
     * 根据id查询拼团信息，是否超时失效了
     * @param key
     * @return
     */
    public PtCaptain findByFatherId(String key) {
        return ptCaptainDAO.findByFatherId(key);
    }

    /**
     * Redis监听到了发起拼团的订单失效，设置拼团状态
     * @param id
     * @param i
     */
    public void setPtCaptainStatus(int id, int i) {
        ptCaptainDAO.updateStatus(id,i);
    }

    /**
     * 根据子id查询订单，是否超时失效了
     * @param key
     * @return
     */
    public PtMember findByChildrenId(String key) {
        return ptMemberDAO.findByChildrenId(key);
    }

    /**
     * Redis监听到了参团订单失效，设置拼团状态
     * @param id
     * @param i
     */
    public void setPtMemberStatus(int id, int i) {
        ptMemberDAO.updateStatus(id,i);
    }

    /**
     * 根据订单id查询拼团详情
     * @param out_trade_no
     * @return
     */
    public PtCaptain findCaptainByOrderId(String out_trade_no) {
        return ptCaptainDAO.findByOrderId(out_trade_no);
    }

    /**
     * 根据订单id查询参团详情
     * @param out_trade_no
     * @return
     */
    public PtMember findMemberByOrderId(String out_trade_no) {
        return ptMemberDAO.findByOrderId(out_trade_no);
    }

    /**
     *  拼团失败，归还库存  -->  3个库存
     */
    public void releaseStock(String courseId,int i) {
        sysCourseService.releaseStock(courseId,i);
    }

    /**
     * 查询团单里面有orderId的数据吗，有的话，就是拼团的订单，就释放库存1了
     * @param orderId
     * @return
     */
    public int findPtCaptainCountByOrderId(String orderId){
        return ptCaptainDAO.findPtCaptainCountByOrderId(orderId);
    }


}
